package com.yonyou.cloud.member.config.json;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.core.JsonTokenId;
import com.fasterxml.jackson.core.io.NumberInput;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.yonyou.cloud.member.domainmodel.vo.EntityId;

import java.io.IOException;
import java.util.function.Function;

public abstract class EntityIdJsonDeserializer<T extends EntityId> extends JsonDeserializer<T> implements Function<Long, T> {
    @Override
    public T deserialize(JsonParser p, DeserializationContext ctx) throws IOException, JsonProcessingException {
        Long value = null;
        if (p.hasToken(JsonToken.VALUE_NUMBER_INT)) {
            value = p.getLongValue();
        } else {
            value = _parseLong(p, ctx);
        }
        if (value == null) {
            return null;
        } else {
            return apply(value);
        }
    }

    protected final Long _parseLong(JsonParser p, DeserializationContext ctx) throws IOException {
        switch (p.getCurrentTokenId()) {
            // NOTE: caller assumed to usually check VALUE_NUMBER_INT in fast path
            case JsonTokenId.ID_NUMBER_INT:
                return p.getLongValue();
            case JsonTokenId.ID_STRING:
                String text = p.getText().trim();
                if (text.length() == 0) {
                    return null;
                }
                try {
                    return Long.valueOf(NumberInput.parseLong(text));
                } catch (IllegalArgumentException iae) {
                }
                return (Long) ctx.handleWeirdStringValue(Long.class, text, "not a valid Long value");
            // fall-through
            case JsonTokenId.ID_NULL:
                return null;
        }
        // Otherwise, no can do:
        return (Long) ctx.handleUnexpectedToken(Long.class, p);
    }
}
